package forge

import (
	"fmt"
	"github.com/rs/zerolog/log"
	"satellite/pkg/dbx"
	"sync"
	"time"
)

type ConnectOption struct {
	Host       string
	Port       int
	User       string
	Password   string
	IsActivate bool
	Num        int
	Duration   time.Duration
}

type Connect struct {
	*ConnectOption
	*Base
}

func NewConnect(opt *ConnectOption) *Connect {
	return &Connect{
		ConnectOption: opt,
	}
}

func (c *Connect) WithBase(base *Base) *Connect {
	c.Base = base
	return c
}

func (c *Connect) Run() error {
	err := c.initPassword()
	if err != nil {
		return err
	}
	return c.runConnect()
}

func (c *Connect) initPassword() error {
	if c.Password == "" && (c.User == "root" || c.User == "manage") {
		password, err := c.getPassword(c.User)
		if err != nil {
			return err
		}
		c.Password = password
	}
	return nil
}

func (c *Connect) runConnect() error {
	wg := sync.WaitGroup{}
	ch := make(chan int, 1)
	stmt := fmt.Sprintf("select sleep(%d)", c.Duration)
	defer close(ch)
	go func() {
		sn := 0
		fn := 0
		for i := range ch {
			if i == 1 {
				sn++
			} else {
				fn++
			}
		}
		time.Sleep(time.Second)
		log.Info().Int("success", sn).Int("fail", fn).Msg("completed")
	}()
	for i := 0; i < c.Num; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			e, err := dbx.NewEngin(c.Host, c.Port, c.User, c.Password)
			if err != nil {
				ch <- 0
				log.Warn().Err(err).Send()
				return
			}
			defer e.Close()
			ch <- 1
			if c.IsActivate {
				_, err = e.Query(stmt)
				if err != nil {
					return
				}
			} else {
				time.Sleep(c.Duration)
			}
		}()
	}
	wg.Wait()
	return nil
}
